{-# LANGUAGE OverloadedStrings, NoMonomorphismRestriction #-}

module Helem where 

import Data.Tree
import Data.Text (pack)
import Data.Char (toUpper)
import Data.List
import Data.List.Split
import Text.LaTeX hiding (tex)
import Text.LaTeX.Base.Class
import Text.LaTeX.Base.Syntax


main = do
    file <- readFile "ElementCatalog.elem"
    renderFile "ElementCatalog.tex" $ linesToTexList $ filter (/= "") $ map rstrip $ lines file



-- flow
linesToTexList = toTexList . toElemList . toElemForest . toDescForest . toForest



-- strip
wschars :: String
wschars = " \t\r\n"

strip :: String -> String
strip = lstrip . rstrip

lstrip :: String -> String
lstrip s = case s of
                  [] -> []
                  (x:xs) -> if elem x wschars
                            then lstrip xs
                            else s


rstrip = reverse . lstrip . reverse





-- raw
toForest :: [String] -> [Tree String]
toForest [] = []
toForest (x:xs) = (Node x subForest) : (toForest rest)
    where
        (tree,rest) = span (isPrefixOf " ") xs
        subForest = toForest $ map (drop 4) tree

-- (name, desc)
toDescForest :: [Tree String] -> [Tree (String,String)]
toDescForest = fmap $ fmap splitt
    where
        splitl = splitOn ": "
        splitt = (\x -> (x!!0,x!!1)).splitl

-- Elem
data Elem = Elem {
    name :: String,
    parent :: Maybe String,
    leafs :: Maybe String,
    desc :: String}
    deriving (Show)

sortElem = sortBy (\a b -> compare (fmap toUpper $ name a) (fmap toUpper $ name b) ) 

toElemForest :: [Tree (String,String)] -> [Tree Elem]
toElemForest = toElemForest' Nothing

toElemForest' :: Maybe String -> [Tree (String,String)] -> [Tree Elem]
toElemForest' par = map go 
    where
        go (Node (a,b) sub) = Node (Elem a par (pretty $ rake sub) b) (toElemForest' (Just a) sub)
        rake = (intercalate ", " ) . sort . (map (fst . rootLabel))
        pretty s = case s of
            "" -> Nothing
            ok -> Just ok

toElemList :: [Tree Elem] -> [Elem]
toElemList = concatMap flatten




-- Hatex
toTexList :: [Elem] -> LaTeX
toTexList xs = (section $ raw "Element Catalog") <> (tex "In this catalog we document the components of the system by giving a concise description of their roles and responsibilities.") <> (mconcat $ map go (sortElem xs))
    where 
        go e = subsection (fromString $ name e) <> (elemdesc e) -- (mconcat $ map (\(n,f)-> (item $ Just n) <> (tex $ f e)) [("Contained by",parent), ("Contains",leafs), ("Responsibilities",desc)])
        elemdesc e = description $ mconcat [
            maybe mempty (\t -> (item $ Just "Contained by") <> tex t) $ parent e,
            maybe mempty (\t -> (item $ Just "Contains") <> tex t) $ leafs e,
            (item $ Just "Responsibilities") <> (tex $ desc e)]

tex = TeXRaw . pack